/** 
 * @main Plik z definicjami klasy PlikKonfiguracyjny.
 * @file    konfiguracja.cpp
 * @author  Grzegorz Sejnota
 *
 * @created on 1 styczen 2009, 16:47
 * @version 0.0001
 */

#include "konfiguracja.h"
#include "regulatory.h"
#include "wyjatki.h"
#include <iostream>
#include <exception>
#include <vector>
#include <map>
using namespace std;


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++ POCZĄTEK [klasy plikKonfiguracyjny] +++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//======= konstruktor ==========================================================

/**
 * Konstruktor bezargumentowy, prywatny, wykorzystywany w metodzie pobierzInstancje().
 */
PlikKonfiguracyjny::PlikKonfiguracyjny() {
    sciezka = "konfig.txt";
    //plikKonfig.open(sciezka.c_str());
    //if (!plikKonfig){
    //cout<<"BLAD: "<<endl;
    //cout<<"Nie moge otworzyc pliku konfiguracji!"<<endl;
    //}
}

//======= destruktor ===========================================================

/**
 * Destruktor - zamyka strumien plikowy.
 */
PlikKonfiguracyjny::~PlikKonfiguracyjny() {
    if (plikKonfig.is_open()) plikKonfig.close();
}

//======= konstruktor kopiujacy ================================================

/**
 * Pusty konstruktor kopiujacy - stworzony by nie zostal utworzony konstruktor
 * kopiujacy przez kompilator.
 */
PlikKonfiguracyjny::PlikKonfiguracyjny(const PlikKonfiguracyjny &) {
}

//======= funkcja wczytujaca konfiguracje ======================================

/**
 * Wczytuje zawartosc pliku konfiguracyjnego. Zapisuje wszystkie obiekty dyskretne
 * do wektora wskaznikow do klasy ObiektDyskretny.
 */
vector<ObiektDyskretny * > PlikKonfiguracyjny::wczytaj() {
   vector<ObiektDyskretny * > wektorDyskretnych;
    const string start = "==============================",
            koniec = "------------------------------";
    string linia, klucz, wartosc;
    map<string, string> mapaKonfig;

    // ---- otwarcie pliku do odczytu ------------------------------------------
    plikKonfig.open(sciezka.c_str(), ios::in);
    if (!plikKonfig) {
        throw Wyjatek("Blad otwarcia pliku konfiguracyjnego");
    }
    // ---- petla do konca pliku -----------------------------------------------
    while (!plikKonfig.eof()) {
        mapaKonfig.clear();
        getline(plikKonfig, linia);
        if (linia == start) { //znaleziono znak startu
            // ---- petla, przerwana przez znalezienie znaku konca -------------
            while (true) {
                plikKonfig >> klucz;
                if (klucz == koniec) break; //znaleziono znak konca
                getline(plikKonfig, wartosc);
                if (wartosc == koniec) break; //znaleziono znak konca
                mapaKonfig[klucz] = wartosc;
            }
            // ---- wybor typu obiektu ------------------------------------------
            if (mapaKonfig["[typ]="].rfind("armax") != string::npos) {
                //cout<<"Mamy ARMAX"<<endl;
                wektorDyskretnych.push_back(new ObiektARMAX()); // ObiektARMAX
			}else if (mapaKonfig["[typ]="].rfind("regulatorPIDAdapt") != string::npos) {
                //cout<<"Mamy P"<<endl;
				wektorDyskretnych.push_back(new RegulatorPIDAdapt(0)); // RegulatorPIDAdapt
            }else if (mapaKonfig["[typ]="].rfind("regulatorPID") != string::npos) {
                //cout<<"Mamy PIDA"<<endl;
                wektorDyskretnych.push_back(new RegulatorPID(0)); // RegulatorPID
            }else if (mapaKonfig["[typ]="].rfind("regulatorP") != string::npos) {
                //cout<<"Mamy P"<<endl;
                wektorDyskretnych.push_back(new RegulatorP(0)); // RegulatorP
            }else if (mapaKonfig["[typ]="].rfind("regulatorGPC") != string::npos) {
                cout<<"Mamy GPC"<<endl;
                wektorDyskretnych.push_back(new RegulatorGPC()); // RegulatorGPC
			}else if (mapaKonfig["[typ]="].rfind("przekaznikH") != string::npos) {
                //cout<<"Mamy P"<<endl;
				wektorDyskretnych.push_back(new PrzekaznikH(0)); // PrzekaznikH
            }
            // ---- proba utworzenia obiektu ------------------------------------
            try {
                wektorDyskretnych.back()->ustawParametry(mapaKonfig); //ustawiamy parametry
                //wektorDyskretnych.back()->wypiszInfo();
            } catch (Wyjatek &e) {
                cout<<e.pobierzNazwe()<<endl;
                delete wektorDyskretnych.back(); //nie powiodlo sie wiec usuwamy obiekt
                wektorDyskretnych.pop_back();
            }
        }
    }
    plikKonfig.clear();
    plikKonfig.close();
    //cout << endl << "ilosc obietk  " << wektorDyskretnych.size() << endl;    
    return wektorDyskretnych;
}

//======= funkcja zapisujaca konfiguracje ======================================

/**
 * Zapisuje konfiguracje do pliku. Zapisuje wszystkie obiekty dyskretne zawarte
 * w wektorze wskaznikow przekazanym w argumencie.
 *		@param wektorDyskretnych - wektor z wskaznikami obiektow do zapisania
 */
bool PlikKonfiguracyjny::zapisz(const std::vector<ObiektDyskretny * > & wektorDyskretnych) {
    const string start = "==============================",
            koniec = "------------------------------";
    map<string, string> mapaKonfig;
    // ---- otwarcie pliku do zapisu ------------------------------------------
    plikKonfig.open(sciezka.c_str(), ios::out | ios::trunc);
    if (!plikKonfig) {
        throw Wyjatek("Blad otwarcia pliku konfiguracyjnego");
    }
    plikKonfig.exceptions(ios::badbit | ios::failbit); //ustawienie wyjatkow
    try {
        plikKonfig << "    +++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
                "  +                                                   + +\n"
                "+++++++++++++++++++++++++++++++++++++++++++++++++++++   +\n"
                "+                                                   +   +\n"
                "+     PLIK KONFIGURACYJNY PROGRAMU SYMULARMAX       +   +\n"
                "+                                                   + +\n"
                "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
        for (unsigned int i = 0; i < wektorDyskretnych.size(); i++) {
            mapaKonfig = wektorDyskretnych.at(i)->pobierzParametry();
            plikKonfig << start << endl;
            for (map<string, string>::iterator it = mapaKonfig.begin(); it != mapaKonfig.end(); it++) {
                plikKonfig << (it->first) << " " << (it->second) << endl;
            }
            plikKonfig << koniec << endl << endl;
        }
    } catch (fstream::failure e) {
        plikKonfig.clear();
        throw Wyjatek("Blad w trakcie proby zapisu konfiguracji");
    }
    plikKonfig.clear();
    plikKonfig.close();
    return true;
}

//======= operator przypisania =================================================
/**
 * Pusty operator przypisania.
 */
/*
PlikKonfiguracyjny & PlikKonfiguracyjny :: operator=(const PlikKonfiguracyjny&){
}*/


//======= pobierzInstancje =====================================================

/**
 * Metoda tworzaca obiekt klasy PlikKonfiguracyjny lub zwracajaca referencje do
 * jedynego istniejacego jej obiektu - singletonu.
 *      @return referencje do jedynego obiektu klasy PlikKonfiguracyjny
 */
PlikKonfiguracyjny& PlikKonfiguracyjny::pobierzInstancje() {
    //Inicjalizacja statycznego obiektu.
    //Obiekt zostanie utworzony przy pierwszym wywołaniu tej metody
    //i tylko wtedy nastąpi inicjalizacja przy pomocy konstruktora.
    //Każde następne wywołanie jedynie zwróci referencję tego obiektu.
    static PlikKonfiguracyjny instance;
    return instance;
}

//------------------------------------------------------------------------------
//-------------- KONIEC [klasa plikKonfiguracyjny] -----------------------------
//------------------------------------------------------------------------------
